/**
 * 数据库的连接类，如果没有手动调用setConfig，将会从配置表中读取相关的mysql配置数据。
 * 多个数据库会对应不同连接。
 * 如果需要多库联合查询，请在配置表中配置一个高级权限账户，并且将dbName设置为''
 * @author yangxiao
 * @module lib/mysql
 */

import * as mysql from 'mysql';
import * as async from 'async';
import * as serverConfig from '../config/config';

interface mysqlConfig{
    host:string;
    user:string;
    pwd:string;
    dbName:string;
}

export let _rootConnection:mysql.Pool;
export let _connectionPool:mysql.Pool[]=[];
/**
 * 获取上一条执行的sql语句，执行query后，并不能获取本值，需要延迟获取
 */
export let lastSql:any = '';

/**
 * 设置数据库，如果不传入参数，读取默认配置表的。
 * 传入参数中，_path.database为空，系统默认这个为最高Root权限，有跨表操作能力，需要配置相关mysql账户
 */
export function setConfig(_path:mysqlConfig[]=[]){
    
    let callback = (value,index,array)=>{
        if(value.dbName===''){
            _rootConnection= mysql.createPool({
                host   : value.host,
                user   : value.user,
                password : value.pwd,
                database : value.dbName,
            });
        }
        _connectionPool[value.dbName] = mysql.createPool({
            host   : value.host,
            user   : value.user,
            password : value.pwd,
            database : value.dbName,
        });
    }

    if(_path.length===0){
        serverConfig.getServerConfig().mysql.forEach(callback);
    }else{
        _path.forEach(callback);
    }
}
/**
 * 获取数据库连接
 * @param callback 获取连接的回调函数。函数（err,connection)
 * @param dbName 数据库名，如果不传入，将尝试使用配置表中没有设置过dbName的一项配置。
 */
export function getConnection(callback: (err: NodeJS.ErrnoException, connection: mysql.PoolConnection) => any,dbName?){

    if( _connectionPool.length==0 && _rootConnection==null){
        setConfig();
    }
    if(dbName){
        _connectionPool[dbName].getConnection(callback);
    }else{
        if(_rootConnection==null){
            //多库查询，必须在配置表中配置一行dbName为空且账号权限符合的记录。
            console.error("server.json mysql.dbName!=null");
        }
        _rootConnection.getConnection(callback);
    }
}

/**
 * @param dbName 数据库名，如果不传入，将尝试使用配置表中没有设置过dbName的一项配置。
 */
export function query(sql, values, callback?: (err, result?, fields?) => any,dbName?){
    getConnection((err,con:mysql.PoolConnection)=>{
        if(err!=null){
            console.log("lib.mysql.getConnection",err);
            callback(err);
        }
        con.config.queryFormat = queryFormat;
        lastSql = con.query(sql,values,(err,result)=>{
            if(err!=null){
                console.log("lib.mysql.query",err);
            }
            con.release();
            callback(err,result);
        }).sql;
        if(serverConfig.isDebug){
            console.log(con.threadId,lastSql);
        }
       
    },dbName);
}

function queryFormat (query, values){
    if (!values) return query;
    return query.replace(/\:(\w+)/g, function (txt, key) {
        if (values.hasOwnProperty(key)) {
            if(txt==":table"){
                return values[key];
            }
            return this.escape(values[key]);
        }
        return txt;
    }.bind(this));
}
